/*
 * NodeList_for_Two_Way_GB2312.c
 *
 * Created by GF on 2023/3/10.
 */

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "NodeList_for_Two_Way_GB2312.h"

/* NodeList 2W 节点(Node) 初始化 */
struct Node_2W* NodeList_2W_Node_Init() {

    struct Node_2W* Head = (struct Node_2W*)malloc(sizeof(struct Node_2W)); /* 为 节点(Node) 结构体开辟内存, 记录链表的表头用以表示整个链表 */
    /* ********************************************** */
    memset(Head, 0, sizeof(*Head)); /* 调用 memset 函数按字节对内存块进行初始化 */
    /* ********************************************** */
    Head->Prev = NULL; /* 将 NodeList 2W 的 Prev 设置为 NULL */
    Head->Next = NULL; /* 将 NodeList 2W 的 Next 设置为 NULL */
    /* ********************************************** */
    return Head;
}

/* NodeList 2W 获取长度(Length) */
int NodeList_2W_Get_Length(struct Node_2W* Head) {

    if (Head->Next == NULL) {

        return 0;

    } else {

        int Length = 0;
        /* ****************************************** */
         struct Node_2W* MovNode = Head;
        while (MovNode->Next != NULL) {
            
			MovNode = MovNode->Next;
            /* ************************************** */
            if (MovNode != NULL) Length++;
        }

        return Length;
    }
}

/* NodeList 2W 重置 索引(Index) */
void NodeList_2W_Reset_Index(struct Node_2W* Head) {

    if (Head->Next == NULL) {
        
        printf("[Caution] NodeList 2W Reset Index: NodeList 2W is Empty, No Need to Reset Index.\n");
    
    } else {

        int Count = 0;
        
		/* ****************************************** */
        struct Node_2W* MovNode = Head;
        while (MovNode->Next != NULL) {
        	MovNode = MovNode->Next;
        	/* ************************************** */
        	if (MovNode != NULL) MovNode->Idx = Count;
        	/* ************************************** */
        	if (MovNode != NULL) Count++;
		}
    }
}

/* NodeList 2W 末尾添加 节点(Node) 并赋值 */
void NodeList_2W_Append_Node_and_Assign(struct Node_2W* Head, char* StrVal) {

    if (Head->Next == NULL) {
        
        struct Node_2W* NewNode = (struct Node_2W*)malloc(sizeof(struct Node_2W));
        /* ****************************************** */
        strcpy(NewNode->StrVal, StrVal); // 赋值。
        strcpy(NewNode->Type, "String"); // 标示数据类型。 
        
		/* ****************************************** */
        Head->Next = NewNode;
        NewNode->Prev = Head;
        NewNode->Next = NULL;
        
        /* ****************************************** */
        NodeList_2W_Reset_Index(Head); // Calling Other Function.
    
    } else {

        struct Node_2W* MovNode = Head;
        while (MovNode->Next != NULL) MovNode = MovNode->Next;
        
		/* ****************************************** */
        struct Node_2W* NewNode = (struct Node_2W*)malloc(sizeof(struct Node_2W));
        /* ****************************************** */
        strcpy(NewNode->StrVal, StrVal); // 赋值。
        strcpy(NewNode->Type, "String"); // 标示数据类型。
        
		/* ****************************************** */
        MovNode->Next = NewNode;
        NewNode->Prev = MovNode;
        NewNode->Next = NULL;
        
        /* ****************************************** */
        NodeList_2W_Reset_Index(Head); // Calling Other Function.
    }
}

/* NodeList 2W 在指定的索引前面插入 节点(Node) 并赋值 */
void NodeList_2W_Insert_Node_and_Assign(struct Node_2W* Head, int Index, char* StrVal) {

    int Len = NodeList_2W_Get_Length(Head); // Calling Other Function.

    if (Index > Len) {

        NodeList_2W_Append_Node_and_Assign(Head, StrVal); // Calling Other Function.
        /* ****************************************** */
        printf("[Warning] NodeList 2W Insert: Index Exceeds The Length, Appended to The End.\n");

    } else if (Index <= Len) {

        struct Node_2W* NewNode = (struct Node_2W*)malloc(sizeof(struct Node_2W));
        /* ****************************************** */
        strcpy(NewNode->StrVal, StrVal); // 赋值。
        strcpy(NewNode->Type, "String"); // 标示数据类型。
        
		/* ****************************************** */
        // 查找要插入到其前面的节点索引。 
        struct Node_2W* MovNode = Head;
        while (MovNode->Next != NULL) {
		    MovNode = MovNode->Next;
		    /* ************************************** */
		    if (MovNode->Idx == Index) break;
	    }
        
		/* ****************************************** */
        // 创建一个临时节点, 用于临时存放插入位置的前一节点和当前节点。 
        struct Node_2W* TmpNode;
		TmpNode = MovNode->Prev; // 临时存放插入位置的前一节点。 
		/* ****************************************** */
		TmpNode->Next = NewNode;
		NewNode->Prev = TmpNode;
		/* ****************************************** */
		TmpNode = MovNode;      // 临时存放插入位置的当前节点。
		/* ****************************************** */
		TmpNode->Prev = NewNode;
		NewNode->Next = TmpNode;
		
		/* ****************************************** */
        NodeList_2W_Reset_Index(Head); // Calling Other Function.
    }
}

/* NodeList 2W 输出为列表 */
void NodeList_2W_Print_as_List(struct Node_2W* Head) {

    /* 条件判断 : 如果链表头指向的 Next 节点为 NULL */
    if (Head->Next == NULL) {
        
        printf("[Caution] NodeList 2W Doesn't Have Any Node Yet, Print as List Failed.\n");
    
    } else {
        
        printf("[");
        /* ****************************************** */
        struct Node_2W* MovNode = Head;
        while (MovNode->Next != NULL) {
            MovNode = MovNode->Next;
            /* ************************************** */
            if (MovNode != NULL && MovNode->Next != NULL) printf("%s, ", MovNode->StrVal);
            if (MovNode != NULL && MovNode->Next == NULL) printf("%s", MovNode->StrVal);
        }
        /* ****************************************** */
        printf("]\n");
    }
}

/* NodeList 2W 清空 */
void NodeList_2W_Clear(struct Node_2W* Head) {

    /* 条件判断 : 如果链表头指向的 Next 节点为 NULL */
    if (Head->Next == NULL) {
        
        printf("[Caution] NodeList 2W Doesn't Have Any Node Yet, No Need to Clear.\n");
    
    } else {
        
        struct Node_2W* MovNode = Head->Next; // 跳过头节点。 
        while (MovNode != NULL) {
            // 先将要 Free 的节点选定保存到变量中, 再移动节点到要 Free 的节点的下一个节点, 最后 Free 掉选定的节点。 
            struct Node_2W* DelNode = MovNode;
            /* ************************************** */
            MovNode = MovNode->Next;
            /* ************************************** */
            free(DelNode); // 释放选定的节点内存。
        }
        Head->Next = NULL; // 头节点重新赋值 NULL, 否则头节点会链接到 0x10。
    }
}

